local LibItemInfo = LibStub:GetLibrary("LibItemInfo.7000")

-- returns how many hours the server time is ahead of local time
-- convert local time -> server time: add this value
-- convert server time -> local time: subtract this value
function addon:GetServerOffset()
    local serverDate = C_DateAndTime.GetCurrentCalendarTime() -- 1-based starts on Sun
    local serverWeekday, serverMinute, serverHour = serverDate.weekday, serverDate.minute, serverDate.hour
    -- #211: date("%w") is 0-based starts on Sun
    local localWeekday = tonumber(date("%w")) + 1
    local localHour, localMinute = tonumber(date("%H")), tonumber(date("%M"))
    if serverWeekday == (localWeekday + 1) % 7 then -- server is a day ahead
        serverHour = serverHour + 24
    elseif localWeekday == (serverWeekday + 1) % 7 then -- local is a day ahead
        localHour = localHour + 24
    end
    local server = serverHour + serverMinute / 60
    local localT = localHour + localMinute / 60
    local offset = floor((server - localT) * 2 + 0.5) / 2
    return offset
end

function addon:GetRegion()
    if not addon.region then
        local reg
        reg = GetCVar("portal")
        if reg == "public-test" then -- PTR uses US region resets, despite the misleading realm name suffix
            reg = "US"
        end
        if not reg or #reg ~= 2 then
            local gcr = GetCurrentRegion()
            reg = gcr and ({"US", "KR", "EU", "TW", "CN"})[gcr]
        end
        if not reg or #reg ~= 2 then -- other test realms?
            reg = (GetRealmName() or ""):match("%((%a%a)%)")
        end
        reg = reg and reg:upper()
        if reg and #reg == 2 then
            addon.region = reg
        end
    end
    return addon.region
end

function addon:GetNextDailyResetTime()
    local resettime = GetQuestResetTime()
    if
        not resettime or resettime <= 0 or -- ticket 43: can fail during startup
            -- also right after a daylight savings rollover, when it returns negative values >.<
            resettime > 24 * 3600 + 30
     then -- can also be wrong near reset in an instance
        return nil
    end

    return time() + resettime
end

do
    local midnight = {hour = 23, min = 59, sec = 59}
    function addon:GetNextDailySkillResetTime() -- trade skill reset time
        -- this is just a "best guess" because in reality,
        -- different trade skills reset at up to 3 different times
        local rt = addon:GetNextDailyResetTime()
        if not rt then
            return nil
        end
        --local info = date("*t"); print(info.isdst)
        -- Blizzard's ridiculous reset crap:
        -- trade skills ignore daylight savings after the date it changes UNTIL the next restart, then go back to observing it

        return rt
    end
end

function addon:GetNextWeeklyResetTime()
    if not addon.resetDays then
        local region = addon:GetRegion()
        if not region then
            return nil
        end
        addon.resetDays = {}
        addon.resetDays.DLHoffset = 0
        if region == "US" then
            addon.resetDays["2"] = true -- tuesday
            -- ensure oceanic servers over the dateline still reset on tues UTC (wed 1/2 AM server)
            addon.resetDays.DLHoffset = -3
        elseif region == "EU" then
            addon.resetDays["3"] = true -- wednesday
        elseif region == "CN" or region == "KR" or region == "TW" then -- XXX: codes unconfirmed
            addon.resetDays["4"] = true -- thursday
        else
            addon.resetDays["2"] = true -- tuesday?
        end
    end
    local offset = (addon:GetServerOffset() + addon.resetDays.DLHoffset) * 3600
    local nightlyReset = addon:GetNextDailyResetTime()
    if not nightlyReset then
        return nil
    end
    --while date("%A",nightlyReset+offset) ~= WEEKDAY_TUESDAY do
    while not addon.resetDays[date("%w", nightlyReset + offset)] do
        nightlyReset = nightlyReset + 24 * 3600
    end

    return nightlyReset
end

-- 钥石
function RefreshMythicKeyInfo()
    -- 检查钥石
    local mythicKey = {}
    for bagID = 0, 4 do
        for invID = 1, GetContainerNumSlots(bagID) do
            local itemID = GetContainerItemID(bagID, invID)
            if itemID and itemID == 158923 then
                local keyLink = GetContainerItemLink(bagID, invID)
                local KeyInfo = {strsplit(":", keyLink)}
                local mapID = tonumber(KeyInfo[3])
                local mapLevel = tonumber(KeyInfo[4])
                local color
                if KeyInfo[4] == "0" then
                    color = select(4, GetItemQualityColor(0))
                elseif mapLevel >= 15 then
                    color = select(4, GetItemQualityColor(5))
                elseif mapLevel >= 10 then
                    color = select(4, GetItemQualityColor(4))
                elseif mapLevel >= 7 then
                    color = select(4, GetItemQualityColor(3))
                elseif mapLevel >= 4 then
                    color = select(4, GetItemQualityColor(2))
                else
                    color = select(4, GetItemQualityColor(1))
                end
                mythicKey["Dungeons"] = C_ChallengeMode.GetMapUIInfo(mapID)
                mythicKey["Level"] = mapLevel
                mythicKey["Color"] = color
                mythicKey["ResetTime"] = addon:GetNextWeeklyResetTime()
                player["MythicKey"] = mythicKey
            end
        end
    end

    -- 检查本周最佳钥匙
    local mythicKeyBest = {}

    if mythicKeyBest and (mythicKeyBest.ResetTime or 0) < time() then -- dont know weekly reset function will run early or not
        if mythicKeyBest.level and mythicKeyBest.level > 0 then
            mythicKeyBest.LastWeekLevel = mythicKeyBest.level
        end
    end
    mythicKeyBest = mythicKeyBest or {}
    mythicKeyBest["ResetTime"] = addon:GetNextWeeklyResetTime()
    mythicKeyBest["Level"] = C_MythicPlus.GetWeeklyChestRewardLevel()
    mythicKeyBest["WeeklyReward"] = C_MythicPlus.IsWeeklyRewardAvailable()
    player["MythicKeyBest"] = mythicKeyBest
end

-- 刷新个人信息
function RefreshPlayerInfo()
    -- 阵营
    local faction = UnitFactionGroup("player")
    if faction == "Alliance" then
        player["Faction"] = "联盟"
    else
        player["Faction"] = "部落"
    end

    -- 种族
    local race, _ = UnitRace("player")
    player["Race"] = race

    -- 职业
    local LClass, _ = UnitClass("player")
    player["LClass"] = LClass

    -- 等级
    local level = UnitLevel("player")
    player["Level"] = level

    -- 史诗地下城
    player["Dungeons"] = {
        ["Statistic12773"] = GetStatistic(12773), -- 围攻伯拉勒斯
        ["Statistic12745"] = GetStatistic(12745), -- 地渊孢林
        ["Statistic12776"] = GetStatistic(12776), -- 塞塔里斯神庙
        ["Statistic12782"] = GetStatistic(12782), -- 托尔达戈
        ["Statistic12779"] = GetStatistic(12779), -- 暴富矿区
        ["Statistic12785"] = GetStatistic(12785), -- 维克雷斯庄园
        ["Statistic12752"] = GetStatistic(12752), -- 自由镇
        ["Statistic12763"] = GetStatistic(12763), -- 诸王之眠
        ["Statistic12749"] = GetStatistic(12749), -- 阿塔达萨
        ["Statistic12768"] = GetStatistic(12768), -- 风暴神殿
        ["Statistic13620"] = GetStatistic(13620) -- 麦卡贡行动
        -- ["Statistic13620"] = GetStatistic(13620), -- 麦卡贡-车间
        -- ["Statistic13620"] = GetStatistic(13620) -- 麦卡贡-垃圾场
    }

    -- 神器
    local azeriteItemLocation = C_AzeriteItem.FindActiveAzeriteItem()
    if azeriteItemLocation and azeriteItemLocation:IsEquipmentSlot() then
        local xp, totalLevelXP = C_AzeriteItem.GetAzeriteItemXPInfo(azeriteItemLocation)
        local currentLevel = C_AzeriteItem.GetPowerLevel(azeriteItemLocation)
        player["ArtifactLevel"] = currentLevel
        player["ArtifactXP"] = xp / totalLevelXP * 100
    end

    -- 装等
    local IL, ILe = GetAverageItemLevel()
    if IL and tonumber(IL) and tonumber(IL) > 0 then
        local IL, ILe = tonumber(IL), tonumber(ILe)
        player["ILe"] = ILe
        player["IL"] = IL
    end

    -- 披风
    _, level, name, link, quality = LibItemInfo:GetUnitItemInfo("player", 15)
    player.BackslotLevel = level

    -- 刷新钥石信息
    RefreshMythicKeyInfo()
end
